﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using RooHui.Infrastructure.Entities.EFContext;
using RooHui.Infrastructure.Entities.Repository;
using RooHui.Infrastructure.Entities.Enum;
using RooHui.Infrastructure.Entities.EntityCode;
using System.Threading;
using RooHui.Tool;

namespace RooHui.Infrastructure.Entities.Entity
{
    public class Account : IAccessible<U_Account, Account>, ILogicEntity<U_Account, Account>
    {
        static Dictionary<string, object> accountLock = new Dictionary<string, object>();
        static object key = new object();

        public string UserName { get; set; }
        public AccountPlatfrom Platfrom { get; set; }
        public string AccountNo { get; set; }
        public decimal BalanceAmount { get; set; }
        public decimal FrozenAmount { get; set; }

        /// <summary>
        /// 冻结投资笔数
        /// </summary>
        public int FrozenCount { get; set; }
        /// <summary>
        /// 待回款利息
        /// </summary>
        public decimal Accrual { get; set; }
        /// <summary>
        /// 总利息收益
        /// </summary>
        public decimal TotalAccrual { get; set; }
        /// <summary>
        /// 待回款本金
        /// </summary>
        public decimal Corpus { get; set; }
        /// <summary>
        /// 总投资额
        /// </summary>
        public decimal TotalCorpus { get; set; }

        protected override void Covariant(U_Account model)
        {
            if (model != null)
            {
                this.AccountNo = model.AccountNo;
                this.BalanceAmount = model.BalanceAmount;
                this.FrozenAmount = model.FrozenAmount;
                this.Platfrom = (AccountPlatfrom)model.Platfrom;
                this.UserName = model.UserName;
            }
        }

        protected override U_Account Inverter(Account model)
        {
            if (model != null)
            {
                return new U_Account()
                {
                    AccountNo = model.AccountNo,
                    BalanceAmount = model.BalanceAmount,
                    FrozenAmount = model.FrozenAmount,
                    Platfrom = (int)model.Platfrom,
                    UserName = model.UserName
                };
            }
            return null;
        }

        public Account Set(U_Account dbModel)
        {
            Covariant(dbModel);
            return this;
        }
        
        /// <summary>
        /// 将启用缓存,通过username查找
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public override Account Find(string key)
        {
            var o = GetLockKey(key);
            Account account = null;
            if (Monitor.TryEnter(o, 60000))
            {
                account = new AccountCache().GetItem(key);
                Monitor.Exit(o);
            }
            return account;
        }
        public override Account PostDelete()
        {
            new AccountCache().RefreshItem(UserName);
            return base.PostDelete();
        }
        public override Account PostModify()
        {
            var o = GetLockKey(UserName);
            Account account = null;
            if (Monitor.TryEnter(o, 60000))
            {
                new AccountCache().RefreshItem(UserName);
                account = base.PostModify();
                Monitor.Exit(o);
            }
            return account;
        }

        public static Account ChangeAccount(string userName, decimal changeBalanceAmount, decimal changeFrozenAmount)
        {
            var o = GetLockKey(userName);
            Account account = null;
            if (Monitor.TryEnter(o, 60000))
            {
                try
                {
                    account = new Account().Find(c => c.UserName == userName);
                    if (changeBalanceAmount < 0 && account.BalanceAmount < changeBalanceAmount)
                    {
                        Monitor.Exit(o);
                        return account;
                    }
                    if (changeFrozenAmount < 0 && account.FrozenAmount < changeFrozenAmount)
                    {
                        Monitor.Exit(o);
                        return account;
                    }
                    account.BalanceAmount += changeBalanceAmount;
                    account.FrozenAmount += changeFrozenAmount;
                    account = account.PostModify();
                }
                catch (Exception e)
                {
                    LogHelper.Write(CommonLogger.Application, LogLevel.Error, e);
                }
                Monitor.Exit(o);
            }
            return account;
        }
        /// <summary>
        /// 验证余额
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="Amount"></param>
        /// <returns></returns>
        public static bool CheckBalanceAmount(string userName, decimal Amount)
        {
            var o = GetLockKey(userName);
            if (Monitor.TryEnter(o, 60000))
            {
                using (Context ctx = new Context())
                {
                    var data = (from c in ctx.Account
                                where c.UserName == userName
                                select c.BalanceAmount).FirstOrDefault();
                    bool isAdequate = data >= Amount;
                    Monitor.Exit(o);
                    return isAdequate;
                }
            }
            return false;
        }

        private static object GetLockKey(string userName)
        {
            if (!accountLock.ContainsKey(userName))
            {
                lock (key)
                {
                    if (!accountLock.ContainsKey(userName))
                    {
                        accountLock.Add(userName, new object());
                    }
                }
            }
            return accountLock[userName];
        }
    }
}
